package com.mlkj.ytdc.modules;

import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.util.DisplayMetrics;
import android.webkit.MimeTypeMap;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.FileProvider;


import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.WritableMap;
import com.mlkj.ytdc.BuildConfig;
import com.mlkj.ytdc.utils.Event;
import com.mlkj.ytdc.utils.RootUtil;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

import com.huawei.hms.hmsscankit.ScanUtil;
import com.huawei.hms.ml.scan.HmsScan;
import com.huawei.hms.ml.scan.HmsScanAnalyzerOptions;

// 必须实现 ReactContextBaseJavaModule
public class Module extends ReactContextBaseJavaModule {

    public Module(@NonNull ReactApplicationContext reactContext) {
        super(reactContext);

        ctx = reactContext;
    }

    @NonNull
    @Override
    public String getName() {
        return "Module"; // 暴露给RN的模块名, 在JS端通过 NativeModules.Module 即可访问到本模块
    }

    //////////////////// 上面是固定写法
    private Toast mToast;
    // 上下文
    public static ReactApplicationContext ctx;
    public static final String LOG_EVENT_KEY = "log"; // log事件key
    /**
     * 二维码扫描结果事件key
     */
    public static final String SCAN_RESULT_EVENT_KEY = "SCAN_RESULT";
    /**
     * 二维码扫描结果数据key
     */
    public static final String SCAN_RESULT_DATA_KEY = "SCAN_RESULT_DATA";

    @Nullable
    @Override
    // 获取模块预定义的常量值(可以给到JS端使用)
    public Map<String, Object> getConstants() {
        final Map<String, Object> constants = new HashMap<>();
        constants.put("LOG_EVENT_KEY", LOG_EVENT_KEY);
        constants.put("SCAN_RESULT_EVENT_KEY", SCAN_RESULT_EVENT_KEY);
        constants.put("SCAN_RESULT_DATA_KEY", SCAN_RESULT_DATA_KEY);
        return constants;
    }

    /**
     * showToast 封装
     * 添加 @ReactMethod 注解, 然后方法定义为 public void 则可以给到 JS端 使用
     */
    @ReactMethod
    public void showToast(String msg) {
        if (mToast == null) {
            mToast = Toast.makeText(ctx, msg, Toast.LENGTH_SHORT);
        } else {
            mToast.setText(msg);
        }
        mToast.show();
    }

    /**
     * 重启app
     */
    @ReactMethod
    public void restartApp() {
        // 获取应用程序的包名
        String packageName = ctx.getPackageName();

        // 创建一个启动主活动的意图
        Intent intent = ctx.getPackageManager().getLaunchIntentForPackage(packageName);
        if (intent != null) {
            // 设置标志以在启动活动时创建新任务
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            // 清除之前的任务栈
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
            // 启动主活动
            ctx.startActivity(intent);
        }
    }

    /**
     * 获取 app 的信息
     *
     * @param promise
     */
    @ReactMethod
    public void getAppInfo(Promise promise) {
        try {
            // 获取PackageManager实例
            PackageManager packageManager = ctx.getPackageManager();
            WritableMap map = Arguments.createMap();
            map.putString("versionName", BuildConfig.VERSION_NAME);
            map.putInt("versionCode", BuildConfig.VERSION_CODE);
            map.putString("packageName", ctx.getPackageName());
            map.putString("buildDate", BuildConfig.BUILD_DATE);
            promise.resolve(map);
        } catch (Exception e) {
            Event.logEmit(e.getMessage());
            promise.resolve(null);
        }
    }

    /**
     * 获取屏幕分辨率
     */
    @ReactMethod
    public void getPixel(Promise promise) {
        try {
            DisplayMetrics metrics = new DisplayMetrics();
            ctx.getCurrentActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
            int realWidth = metrics.widthPixels;
            int realHeight = metrics.heightPixels;
            WritableMap map = Arguments.createMap();
            map.putInt("width", realWidth);
            map.putInt("height", realHeight);
            promise.resolve(map);
        } catch (Exception e) {
            Event.logEmit(e.getMessage());
            promise.resolve(null);
        }
    }

    /**
     * 使用 fileprovider + Intent 启动系统的 Activity
     *
     * @param url     资源路径
     * @param fileExt 文件后缀名, 会转换为 mimeType, 例如: png -> 查看图片(image/png), apk -> 安装APK(application/vnd.android.package-archive)
     * @param promise
     */
    @ReactMethod
    public void actionViewIntent(String url, String fileExt, Promise promise) {
        Intent installintent = new Intent();
        installintent.setAction(Intent.ACTION_VIEW);
        // 启动活动添加Intent.FLAG_ACTIVITY_NEW_TASK
        installintent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        // 路径
        File file = new File(url);

        String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExt);

        try {
            // 判断安卓系统是否大于7.0  大于7.0使用以下方法
            if (Build.VERSION.SDK_INT >= 24) {
                // 转为URI格式  第二个参数为AndroidManifest.xml中定义的authorities的值
                Uri uri = FileProvider.getUriForFile(ctx, ctx.getPackageName() + ".fileprovider", file);
                // 对目标应用临时授权该Uri所代表的文件
                installintent.addFlags(installintent.FLAG_GRANT_READ_URI_PERMISSION);
                installintent.setDataAndType(uri, mimeType);
            } else {
                installintent.setDataAndType(Uri.fromFile(file), mimeType);
            }

            // 启动
            ctx.startActivity(installintent);
            promise.resolve(null);
        } catch (Exception e) {
            promise.resolve(e.getMessage());
            Event.logEmit("发生错误: " + e.getMessage());
        }
    }

    /**
     * 执行 shell 命令
     *
     * @param cmd     命令字符串
     * @param isRoot  是否 Root
     * @param promise
     */
    @ReactMethod
    public void execShell(final String cmd, boolean isRoot, Promise promise) {
        int result = -1;
        Process process = null;
        BufferedReader successResult = null;
        BufferedReader errorResult = null;
        StringBuilder stdout = null;
        StringBuilder stderr = null;
        DataOutputStream os = null;

        WritableMap map = Arguments.createMap();

        try {
            process = Runtime.getRuntime().exec(isRoot ? "su" : "sh");
            os = new DataOutputStream(process.getOutputStream());

            os.write(cmd.getBytes());
            os.writeBytes("\n");
            os.flush();

            os.writeBytes("exit\n");
            os.flush();
            result = process.waitFor();
            stdout = new StringBuilder();
            stderr = new StringBuilder();
            successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
            errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));

            String s;
            while ((s = successResult.readLine()) != null) {
                stdout.append(s);
            }

            while ((s = errorResult.readLine()) != null) {
                stderr.append(s);
            }
        } catch (IOException e) {
            Event.logEmit("发生了错误: " + e.getMessage());
        } catch (Exception e) {
            Event.logEmit("发生了错误: " + e.getMessage());
        } finally {
            try {
                if (os != null) {
                    os.close();
                }

                if (successResult != null) {
                    successResult.close();
                }

                if (errorResult != null) {
                    errorResult.close();
                }
            } catch (IOException e) {
                Event.logEmit("发生了错误: " + e.getMessage());
            }

            if (process != null) {
                process.destroy();
            }

            map.putString("stdout", String.valueOf(stdout));
            map.putString("stderr", String.valueOf(stderr));
            map.putInt("exitValue", result);

            promise.resolve(map);
        }
    }

    /**
     * 判断是否已经 root
     */
    @ReactMethod
    public void isRoot(Promise promise) {
        promise.resolve(RootUtil.isDeviceRooted());
    }

    /**
     * 关机
     */
    @ReactMethod
    public void shutdown(Promise promise) {
        execShell("reboot -p", true, promise);
    }

    /**
     * 重启
     *
     * @param promise
     */
    @ReactMethod
    public void reboot(Promise promise) {
        execShell("reboot", true, promise);
    }

    /**
     * 重启
     */
    @ReactMethod
    public void test(Promise promise) {

        
    }

    /**
     * 修改系统时间, 只支持 Android5
     */
    @ReactMethod
    public static void setSystemTime(String time, Promise promise) {
        try {
            Process process = Runtime.getRuntime().exec("su");
            // 格式为: 年月日.时分秒, 例如: 20210101.120000
            DataOutputStream os = new DataOutputStream(process.getOutputStream());
            os.writeBytes("setprop persist.sys.timezone GMT\n");
            os.writeBytes("/system/bin/date -s " + time + "\n");
            os.writeBytes("clock -w\n");
            os.writeBytes("exit\n");
            os.flush();
            promise.resolve(null);
        } catch (Exception e) {
            Event.logEmit("修改系统时间失败: " + e.getMessage());
            promise.resolve(e.getMessage());
        }
    }

    public static final int REQUEST_CODE_SCAN = 0x01;
    /**
     * 跳转扫码页面
     */
    @ReactMethod
    public void gotoScanQrCode() {
        Activity currentActivity = this.getCurrentActivity();
        // ScanUtil.startScan(currentActivity, REQUEST_CODE_SCAN, new HmsScanAnalyzerOptions.Creator().setHmsScanTypes(HmsScan.ALL_SCAN_TYPE).create());
        ScanUtil.startScan(currentActivity, REQUEST_CODE_SCAN, new HmsScanAnalyzerOptions.Creator().setHmsScanTypes(HmsScan.QRCODE_SCAN_TYPE).create());
    }
}
